#ifndef __P_PARSER_H__
#define __P_PARSER_H__

#include "p_types.h"
#include "p_error.h"
#include "p_lexer.h"

#include <string>

// struct forward definition...
struct p_parser_struct;

// typedefs...
typedef p_parser_struct* p_parser_struct_ptr;

/**
 * This is the main implementation of the parser. Each parser is represented by such an object.
 *
 * @brief This is the parser object.
 */
struct p_parser_struct
{
   p_token_struct_list_ptr token_list;
   // here are many more entries such as function tables and other stuff...
   // ... such as the abstract syntax tree.
   p_unsigned_int token_index;

   bool lvalue_expression;

   static const p_token_struct EOF_TOKEN;
};

/**
 * This function creates a parser object.
 */
p_parser_struct parser_struct_create();

/**
 * This function initializes a given parser object.
 *
 * @param parser A pointer to a parser struct used to initialize every member of the object.
 */
void parser_struct_init(p_parser_struct_ptr parser);

/**
 * This function frees every internally used memory of a parser object.
 *
 * @param parser A pointer to a parser object, which members are freed.
 */
void parser_struct_clean_up(p_parser_struct_ptr parser);

/**
 * This function initializes the a parser object and returns a pointer.
 * The object is allocated using the new operator.
 */
p_parser_struct_ptr parser_struct_new();

/**
 * This functions frees all the memory of a previously created parser object.
 *
 * @param parser A pointer to a parser object.
 */
void parser_struct_destroy(p_parser_struct_ptr parser);

/**
 * This is the main parser function for parsing programs.
 */
void parser_struct_parse(p_parser_struct_ptr parser);

/**
 * This function invokes the parser on a file or on an immediate input.
 *
 * @param file_name_or_content As the parameter states it't either a file name or content.
 * @param is_file_name Tells whether the first parameter denotes a file or not.
 */
p_parser_struct_ptr parser_parse(const std::string &file_name_or_content,
                                 const bool &is_file_name);

/**
 * This function parses the given program.
 *
 * @param program The program as a string.
 */
p_parser_struct_ptr parser_parse(const std::string &program);

/**
 * This function parses the given file.
 *
 * @param file_name This is the file which is parsed. The file is opened only for reading.
 */
p_parser_struct_ptr parser_parse_file(const std::string &file_name);

const p_token_struct& next_token(p_parser_struct_ptr parser);

const p_token_struct& test_token(p_parser_struct_ptr parser);

void parser_parse_type_expression(p_parser_struct_ptr parser,
                                  const bool &check_semicolon);

#endif
